%option stack
%{

#include <stdlib.h>
/* Include this file to indentify tokens. 
Use bison -d filename.y to generate parser
*/

#include "parse.tab.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct stack_node {
  int indentation;
  struct stack_node *next;
} *temp_node;

struct stack_node* newnode();
static struct stack_node *stack_top = NULL;
%}


escapeseq      		\\(.|\n)(?# "\" <any ASCII character>)
longstringchar 		[^\\](?# <any source character except "\">)
shortstringchar               [^\\|\'|\"|\n](?# <any source character except "\" or newline or the quote>)
longstringitem 		{longstringchar}|{escapeseq}
shortstringitem               {shortstringchar}|{escapeseq}
longstring     (\'\'\'{longstringitem}*\'\'\')|(\"\"\"{longstringitem}*\"\"\")
shortstring    (\'{shortstringitem}*\')|(\"{shortstringitem}*\")
stringprefix	'r'|'u'|'(ur)'|'R'|'U'|'(UR)'|'(Ur)'|'(uR)'
stringliteral	{stringprefix}?({shortstring}|{longstring})

DIGIT [0-9]
ID [a-zA-Z][a-zA-Z0-9]*

%x FORDEDENT
%%

%{


	int current_indentation = 0;
	int i;
	int len=0;
	int flag=0;

%}

print   return PRINT;
and	return  AND;
del	return  DEL;
from	return  FROM;
not	return  NOT;
while	return  WHILE;
as	return  AS;
elif	return  ELIF;
global	return  GLOBAL;
or	return  OR;
with	return  WITH;
assert	return  ASSERT;
else	return  ELSE;
if	return  IF;
pass	return  PASS;
yield	return  YIELD;
break	return  BREAK;
except	return  EXCEPT;
import  return  IMPORT;
class	return  CLASS;
exec	return  EXEC;
in	return  IN;
raise	return  RAISE;
continue return  CONTINUE;
finally	return  FINALLY;
is	return  IS;
return	return  RETURN;
def	return  DEF;
for	return  FOR;
lambda	return  LAMBDA;
try	return  TRY;

"+="  	return INCEQ;
"-="  	return DECEQ;
"*="  	return MULEQ;
"/=" 	return DIVEQ;
"%="  	return MODEQ;
"&="  	return ANDEQ;
"|="  	return OREQ;
"^="  	return NOTEQ;
"<<=" 	return LSFTEQ;
">>=" 	return RSFTEQ;
"**="   return EXPEQ;
"<" 	return LT;
">" 	return GT;
"==" 	return EQ;
">=" 	return GE;
"<=" 	return LE;
"!=" 	return NE;
","	return COMMA;
":"	return COLON;
";"	return SEMICOLON;
"="	return EQUAL;
"."	return DOT;
"("	return LP;
")"	return RP;
"+"	return PLUS;
"-"	return MINUS;
"~"	return TILDE;
"*"	return STAR;
"\\"	return DIV;
"["	return LB;
"]"	return RB;
"{"	return LCB;
"}"	return RCB;
"\\\\"	return DSLASH; 
"%"	return PERCENT; 
"|"     return PIPE;
"^"     return CAP;
"&"     return AMPRSND;
<FORDEDENT>.* 	{
			temp_node = stack_top;
			stack_top = stack_top -> next;
			free (temp_node);
			printf("DEDENT");
			yyless(len-2);
			if(stack_top -> indentation <= current_indentation)
				BEGIN(0);
			
		}
			
\\\n	/* explicit line joining */

\n	return NEWLINE;

[ \t]*'#'.*	/* comment line */

^[ \t]*. {
		current_indentation = 0;
		if(stack_top == NULL)
			stack_top= newnode();
		for (i = 0; yytext[i] != '\0'; i++)	
			if(yytext[i] == ' ')
				current_indentation += 1;
			else if(yytext[i] == '\t')
				current_indentation += 8;
		len= strlen(yytext); 
		if (stack_top -> indentation == current_indentation)
		{
			yyless(len-1);
		}
		else if (stack_top -> indentation < current_indentation) {
			temp_node = malloc (sizeof(struct stack_node));
			temp_node -> indentation = current_indentation;
			temp_node -> next = stack_top;
			stack_top = temp_node;
			return INDENT;
			yyless(len-1);
		}
		else if (stack_top -> indentation > current_indentation) {
			BEGIN(FORDEDENT);
			yyless(len-1);
		}
	} 

{DIGIT}+ {	
		yylval.intval = atoi(yytext);
		return(NUMBER);
	 }
{ID} 	{
		yylval.id=(char *) strdup(yytext);
		return(IDENTIFIER);
	}
\.[0-9][0-9]*	return FRACTION;

[eE]([+-])?[0-9][0-9]*	return EXPONENT;

{stringliteral}	{return STRING;}

%%

struct stack_node* newnode()
{
	
	struct stack_node *new_node = malloc (sizeof(struct stack_node));
	new_node -> indentation = 0;
	new_node -> next = NULL;
	return new_node;
}
	
